#ifndef SIMPLE_IO_RESIZE_H
#define SIMPLE_IO_RESIZE_H

#include <cstddef> // std::size_t
#include <variant> // std::variant std::monostate std::visit
#include <type_traits> // std::enable_if_t
#include <string> // std::string
#include <utility> // std::forward

#include "simple/support/meta/pend.hpp" // support::meta::append_t

#include "error.h" // error
#include "write_resize_common.h" // size_limit_reached not_write_handle
#include "handle.h" // unique_hanlde operation interface

namespace simple::io
{
	namespace meta = support::meta;

	using resize_result = std::variant<std::monostate,
		size_limit_reached,
		error
	>;

	using ex_resize_result = meta::append_t<resize_result, not_write_handle>;

	[[nodiscard]]
	ex_resize_result resize(const unique_handle&, std::size_t) noexcept;

	template <operation allowed,
		std::enable_if_t<allowed && operation::write>* = nullptr>
	resize_result resize(const interface<allowed>& i, std::size_t size) noexcept
	// TODO: return to<resize_result>(resize(i.handle, s));
	{ return std::visit([](auto&& x){ return resize_result(x); }, resize(i.handle, size)); }

	constexpr struct resize_f_t
	{
		template <typename... Args>
		[[nodiscard]] decltype(auto) operator()(Args&& ... args) const noexcept
		{ return simple::io::resize(std::forward<Args>(args)...); }
	} resize_f;

	[[nodiscard]] inline std::string get_message(const resize_f_t&)
	{ return "simple::io::resize"; }

} // namespace simple::io

#endif /* end of include guard */
